/**
 * eCommerce Application Sample for J2EE Training
 * Implementation of EcomCustomerBean
 * @author Fabienne Boyer - Didier Donsez
 * may 2006
 */
package ecom.session;

import ecom.cart.CartItem;
import ecom.dao.AdressDAO;
import ecom.dao.CategoryDAO;
import ecom.dao.CountryDAO;
import ecom.dao.CustomerDAO;
import ecom.dao.OrdersDAO;
import ecom.dao.ProductDAO;
import ecom.dao.ProductStoreDAO;
import ecom.dao.StoreDAO;
import ecom.dao.TransactionnalDAO;
import ecom.entity.Adress;
import ecom.entity.Category;
import ecom.entity.Country;
import ecom.entity.Customer;
import ecom.entity.Orders;
import ecom.entity.Product;
import ecom.entity.ProductStore;
import ecom.entity.ProductStorePK;
import ecom.entity.Purchase;
import ecom.entity.Store;
import ecom.entity.TransportEnum;
import ecom.exception.EcomException;
import java.util.List;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.ejb.EJB;

public class EcomGenericBean {



    /**
     * Liste tous les magasins
     * @return la liste des stores
     */
    public List<Store> listStore() {
        List<Store> stores = null;
        StoreDAO storeDAO = new StoreDAO();
        stores = storeDAO.findAll();
        storeDAO.closeSession();
        return stores;
    }

    /**
     *  Liste tous les produits
     * @return  la liste des produits
     */
    public List<Product> listProducts() {
        List<Product> productList = null;
        ProductDAO productDAO = new ProductDAO();
        productList = productDAO.findAll();
        productDAO.closeSession();
        return productList;
    }

    /**
     * liste les produits d'un store
     * @param idStore
     * @return la liste des produits d'un store
     */
    public List<ProductStore> listProductsStore(int idStore) {
        List<ProductStore> productStoreList = null;
        ProductStoreDAO productStoreDAO = new ProductStoreDAO();
        productStoreList = productStoreDAO.findProductsByStore(idStore);
        productStoreDAO.closeSession();
        return productStoreList;
    }

    /**
     * Liste les produits d'un catégorie
     * @param idCategory
     * @return une liste de produit
     */
    public List<Product> listProductsByCategory(int idCategory) {
        List<Product> productList = null;
        ProductDAO productDAO = new ProductDAO();
        productList = productDAO.findAllByCategory(idCategory);
        productDAO.closeSession();
        return productList;
    }

    /**
     * Permet de lister les country afin de saisir la totalite de l'adresse pour la creation d'un customer
     */
    public List<Country> listCountry() {
        List<Country> countryList = null;
        CountryDAO dao = new CountryDAO();
        countryList = dao.findAll();
        return countryList;
    }

    /**
     * Retrouve un produit à partir d'un id Produit
     * @param productId
     * @return  product
     */
    public Product findProductById(int productId) {
        Product product = new Product();
        ProductDAO productDAO = new ProductDAO();
        product = productDAO.findById(productId);
        productDAO.closeSession();
        return product;
    }

    public Product findProductByName(String productName) {
        Product product = new Product();
        ProductDAO productDAO = new ProductDAO();
        product = productDAO.findByName(productName);
        productDAO.closeSession();
        return product;
    }

    public List<Product> findProductsByInName(String productInName) {
        List<Product> listProduct = null;
        ProductDAO productDAO = new ProductDAO();
        listProduct = productDAO.findByInName(productInName);
        productDAO.closeSession();
        return listProduct;
    }

    public List<Product> findProductsByMaxPrice(Double maxPrice) {
        List<Product> listProduct = null;
        ProductDAO productDAO = new ProductDAO();
        listProduct = productDAO.findByPriceUnder(maxPrice);
        productDAO.closeSession();
        return listProduct;
    }

    public void deleteProduct(int idProduct) {
        Product product = null;
        ProductDAO productDAO = new ProductDAO();
        product = productDAO.findById(idProduct);
        productDAO.delete(product);
        productDAO.closeSession();
    }


    /**
     * 
     * @return 
     */
    public List<Category> listCategories() {
        CategoryDAO categoryDAO = new CategoryDAO();
        List<Category> categories = categoryDAO.findAll();
        categoryDAO.closeSession();
        return categories;
    }

    /**
     * 
     * @return 
     */
    public List<Store> listStores() {
        StoreDAO storeDAO = new StoreDAO();
        List<Store> stores = storeDAO.findAll();
        storeDAO.closeSession();
        return stores;
    }

    /**
     * Affiche le compte d'un client
     * @param customer
     * @return the balance of the customer
     */
    public double getBalanceCustomer(Customer customer) {
        return customer.getAccount().getBalance();
    }

    /**
     * Reouvr le client à partir de l'email et le mot de passe entré
     * @param email
     * @param password
     * @return 
     */
    public Customer login(String email, String password) {
        Customer c = null;
        CustomerDAO customerDAO = new CustomerDAO();
        c = customerDAO.findByEmail(email);
        return c;
    }

//    public void addProductToCart(Product product, double price, int storeId) {
//        cart.addItem(product, price, storeId);
//    }

    /**
     * Permet de valider les achat a partir d'un panier
     * @param cartItems : contient les items du panier
     * @param customer : permet de connaitre le client qui effectue l'achat pour debiter son compte
     * @param adress : adresse de livraison
     */
    public void purchase (List<CartItem> cartItems, Customer customer, Adress adress) throws EcomException {
        // creation des variables necessaires
        TransactionnalDAO transac = new TransactionnalDAO();
        ProductStoreDAO productStoreDAO = new ProductStoreDAO();
        Orders order = new Orders();
        List<Purchase> purchaseList = new ArrayList<Purchase>();
        List<ProductStore> productStoreList = new ArrayList<ProductStore>();
        Map<Integer, Double> mappingStoreAccount = new HashMap<Integer, Double>();
        double shipping = TransportEnum.POSTE.getPrice();
        double total = 0;

        for (CartItem item : cartItems) {
            Purchase p = new Purchase();
            p.setProduct(item.getProduct());
            p.setQuantity(item.getQuantity());
            p.setUnitPrice(item.getPrice());

            // ajout de chaque purchase dans la list
            purchaseList.add(p);

            // on gere le total a crediter du compte pour chaque magasin avec une Map
            if (mappingStoreAccount.containsKey(item.getStoreId())) {
                Double totalAccountToCredit = mappingStoreAccount.get(item.getStoreId());
                totalAccountToCredit += item.getTotal();

                // on ne peut update une map donc on remove pour la remetre
                mappingStoreAccount.remove(item.getStoreId());
                mappingStoreAccount.put(item.getStoreId(), totalAccountToCredit);

            } else {
                mappingStoreAccount.put(item.getStoreId(), item.getTotal());
            }

            // gestion du stock avec les ProductStore
            ProductStorePK pk = new ProductStorePK(item.getStoreId(), item.getProduct().getIdProduct());
            ProductStore productStore = productStoreDAO.find(pk);
            productStore.setId(pk);

            // Verification du stock en magasin
            int stockAfterPurchase = productStore.getStock() - item.getQuantity();
            if (stockAfterPurchase < 0) {
                throw new EcomException("Le stock de " + item.getProduct().getName() + " est insuffisant dans le magasin " + productStore.getStore().getName() + ". Voulu : " + item.getQuantity() + ", dispo : " + productStore.getStock());
            }
            
            productStore.setStock(stockAfterPurchase);

            // ajout a la liste de productStore
            productStoreList.add(productStore);

            // Calcul du total a debiter 
            total += item.getTotal();
        }

        
        double customerSoldeAfterPurchase = customer.getAccount().getBalance() - total - shipping;
        
        // Verification du solde du client
        if(customerSoldeAfterPurchase < 0) {
            throw new EcomException("Solde du client insuffisant !");
        }
        
        // modification du solde du compte du client
        customer.getAccount().setBalance(customerSoldeAfterPurchase);

        // realisation de la transaction mise a jour/creation
        // creation de la commande
        order.setAdress(adress);
        order.setCustomer(customer);
        order.setDate(new Date());
        order.setShipping(shipping);
        order.setTransport(TransportEnum.POSTE.getId());
        order.setPurchaseList(purchaseList);
        
        // Realisation de la transaction
        transac.createOrderWithTransaction(order, productStoreList, mappingStoreAccount);
        transac.closeSession();
    }

    public Adress findAdressById(int id) {
        AdressDAO adressDao = new AdressDAO();
        Adress a = adressDao.find(id);
        adressDao.closeSession();
        return a;
    }

    /**
     * Permet d'ajouter une adresse a un client
     * @param adress
     * @param customer
     * @return 
     */
    public Customer addAdressToCustomer(Adress adress, Customer customer) {
        CustomerDAO customerDAO = new CustomerDAO();
        AdressDAO adressDAO = new AdressDAO();

        // creation et ajout de l'adresse
        adressDAO.create(adress);
        customer.getAdressList().add(adress);

        // sauvegarde du customer
        customerDAO.saveOrUpdate(customer);
        return customer;
    }
}
